const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const userDao = require('../dao/userDao');
const { generateToken, generateRefreshToken } = require('../utils/auth');

class UserServices {
  // 用户注册
  async register(userData) {
    try {
      const { username, password, phone, email } = userData;

      // 检查用户名是否已存在
      if (await userDao.isUsernameExists(username)) {
        throw new Error('用户名已存在');
      }

      // 检查手机号是否已存在
      if (phone && await userDao.isPhoneExists(phone)) {
        throw new Error('手机号已存在');
      }

      // 检查邮箱是否已存在
      if (email && await userDao.isEmailExists(email)) {
        throw new Error('邮箱已存在');
      }

      // 密码加密
      const hashedPassword = await bcrypt.hash(password, 10);

      // 创建用户
      const user = await userDao.createUser({
        ...userData,
        password: hashedPassword
      });

      // 移除密码字段
      const userInfo = user.toJSON();
      delete userInfo.password;

      return {
        user: userInfo,
        token: generateToken(user),
        refreshToken: generateRefreshToken(user)
      };
    } catch (error) {
      throw new Error(`注册失败: ${error.message}`);
    }
  }

  // 用户登录
  async login(username, password) {
    try {
      // 查找用户
      const user = await userDao.findByUsername(username);
      if (!user) {
        throw new Error('用户名或密码错误');
      }

      // 验证密码
      const isPasswordValid = await bcrypt.compare(password, user.password);
      if (!isPasswordValid) {
        throw new Error('用户名或密码错误');
      }

      // 检查用户状态
      if (user.status !== 'active') {
        throw new Error('账户已被禁用');
      }

      // 更新最后登录时间
      await userDao.updateLastLogin(user.id);

      // 移除密码字段
      const userInfo = user.toJSON();
      delete userInfo.password;

      return {
        user: userInfo,
        token: generateToken(user),
        refreshToken: generateRefreshToken(user)
      };
    } catch (error) {
      throw new Error(`登录失败: ${error.message}`);
    }
  }

  // 刷新Token
  async refreshToken(refreshToken) {
    try {
      // 验证刷新Token
      const decoded = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET);
      
      // 查找用户
      const user = await userDao.findById(decoded.id);
      if (!user || user.status !== 'active') {
        throw new Error('用户不存在或已被禁用');
      }

      // 生成新的Token
      return {
        token: generateToken(user),
        refreshToken: generateRefreshToken(user)
      };
    } catch (error) {
      throw new Error(`刷新Token失败: ${error.message}`);
    }
  }

  // 获取用户信息
  async getUserProfile(userId) {
    try {
      const user = await userDao.findById(userId);
      if (!user) {
        throw new Error('用户不存在');
      }

      // 移除密码字段
      const userInfo = user.toJSON();
      delete userInfo.password;

      return userInfo;
    } catch (error) {
      throw new Error(`获取用户信息失败: ${error.message}`);
    }
  }

  // 更新用户信息
  async updateUserProfile(userId, updateData) {
    try {
      // 检查用户是否存在
      const existingUser = await userDao.findById(userId);
      if (!existingUser) {
        throw new Error('用户不存在');
      }

      // 如果更新用户名，检查是否重复
      if (updateData.username && updateData.username !== existingUser.username) {
        if (await userDao.isUsernameExists(updateData.username, userId)) {
          throw new Error('用户名已存在');
        }
      }

      // 如果更新手机号，检查是否重复
      if (updateData.phone && updateData.phone !== existingUser.phone) {
        if (await userDao.isPhoneExists(updateData.phone, userId)) {
          throw new Error('手机号已存在');
        }
      }

      // 如果更新邮箱，检查是否重复
      if (updateData.email && updateData.email !== existingUser.email) {
        if (await userDao.isEmailExists(updateData.email, userId)) {
          throw new Error('邮箱已存在');
        }
      }

      // 如果更新密码，进行加密
      if (updateData.password) {
        updateData.password = await bcrypt.hash(updateData.password, 10);
      }

      // 更新用户信息
      const updatedUser = await userDao.updateUser(userId, updateData);

      // 移除密码字段
      const userInfo = updatedUser.toJSON();
      delete userInfo.password;

      return userInfo;
    } catch (error) {
      throw new Error(`更新用户信息失败: ${error.message}`);
    }
  }

  // 修改密码
  async changePassword(userId, oldPassword, newPassword) {
    try {
      // 查找用户
      const user = await userDao.findById(userId);
      if (!user) {
        throw new Error('用户不存在');
      }

      // 验证旧密码
      const isOldPasswordValid = await bcrypt.compare(oldPassword, user.password);
      if (!isOldPasswordValid) {
        throw new Error('原密码错误');
      }

      // 加密新密码
      const hashedNewPassword = await bcrypt.hash(newPassword, 10);

      // 更新密码
      await userDao.updateUser(userId, { password: hashedNewPassword });

      return true;
    } catch (error) {
      throw new Error(`修改密码失败: ${error.message}`);
    }
  }

  // 增加学习时长
  async addStudyTime(userId, seconds) {
    try {
      await userDao.addStudyTime(userId, seconds);
      
      // 根据学习时长增加积分（每分钟1积分）
      const points = Math.floor(seconds / 60);
      if (points > 0) {
        await userDao.addPoints(userId, points);
      }

      return true;
    } catch (error) {
      throw new Error(`更新学习时长失败: ${error.message}`);
    }
  }

  // 增加积分
  async addPoints(userId, points) {
    try {
      await userDao.addPoints(userId, points);
      return true;
    } catch (error) {
      throw new Error(`增加积分失败: ${error.message}`);
    }
  }

  // 获取用户统计信息
  async getUserStatistics(userId) {
    try {
      const user = await userDao.findById(userId);
      if (!user) {
        throw new Error('用户不存在');
      }

      // 这里可以添加更多统计信息的计算
      // 比如从评测记录、游戏记录等表中统计数据
      
      return {
        level: user.level,
        points: user.points,
        studyTime: user.study_time,
        joinDate: user.created_at,
        lastLogin: user.last_login_at
      };
    } catch (error) {
      throw new Error(`获取用户统计失败: ${error.message}`);
    }
  }

  // 验证Token
  async verifyToken(token) {
    try {
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      const user = await userDao.findById(decoded.id);
      
      if (!user || user.status !== 'active') {
        throw new Error('用户不存在或已被禁用');
      }

      // 移除密码字段
      const userInfo = user.toJSON();
      delete userInfo.password;

      return userInfo;
    } catch (error) {
      throw new Error(`Token验证失败: ${error.message}`);
    }
  }
}

module.exports = new UserServices();
